//
//  ClusterLight.cpp
//  Ray Tracer
//
//  Created by Kaila, Ashish on 4/5/13.
//  Copyright (c) 2013 Kaila, Ashish. All rights reserved.
//

#include "ClusterLight.h"
#include "../raytracer.h"
#include "../Materials/Material.h"
#include <stdlib.h>

ClusterLight::ClusterLight(Point3D position,
                         const Vector3D u,
                         const Vector3D v,
                         unsigned int sampleSize,
                         Colour color)
: PointLight(position, (1.0 / (double)(sampleSize * sampleSize)) * color),
_sampleSize(sampleSize)
{
    // Generate random light sources
    for (unsigned int i = 0; i < _sampleSize * _sampleSize; i++)
    {
        double a = (double)rand() / (double)RAND_MAX;
        double b = (double)rand() / (double)RAND_MAX;
        _points.push_back(PointLight::get_position() + (a - 0.5) * u + (b - 0.5) * v);
    }
}

Colour ClusterLight::shadeShadow(Ray3D& ray, ISceneNavigator& sceneNavigator, bool isInShadow)
{
    double r = 0;
    double g = 0;
    double b = 0;
    
    unsigned int sampleSizeSq = _sampleSize * _sampleSize;
    
    if (_points.size() != sampleSizeSq)
    {
        throw "Size mismatch, call isInShadow to generate light positions";
    }
    
    Colour materialColour = ray.col;
    
    for (unsigned int i = 0; i < sampleSizeSq; i++)
    {
        Point3D lightPos = _points[i];
        
        PointLight pointLight(lightPos, getAmbientColour());
        
        Ray3D lightRay;
        lightRay.dir = lightPos - lightRay.origin;
        lightRay.origin = ray.intersection.point;
        
        if (!pointLight.isInShadow(lightRay.origin, sceneNavigator))
        {
            r += materialColour[0];
            g += materialColour[1];
            b += materialColour[2];
        }
    }
    
    return Colour(r / (double)sampleSizeSq, g / (double)sampleSizeSq , b / (double)sampleSizeSq);
}

void ClusterLight::shade(Ray3D& ray)
{
    // Calculate the point light shading for the ray
    PointLight tempLight(get_position(), _sampleSize * _sampleSize * getAmbientColour());
    tempLight.shade(ray);
}
